#include "usb.h"
#include "usb_device.h"
#include "usb_device_class.h"
#include "usb_device_bulk.h"
#include "usb_device_config.h"
#include "usb_device_ch9.h"
#include "usb_device_descriptor.h"
#include "usb_composite.h"
#include "usb_bulk.h"
#include "task.h"

//#include "taskUSBDataTransmit.h"

#if defined(USB_DEVICE_ENABLE_BULK) && (USB_DEVICE_ENABLE_BULK > 0)

USB_DMA_NONINIT_DATA_ALIGN(USB_DATA_ALIGN_SIZE) static uint8_t bulk_rec_buffer[FS_BULK_DEVICE_OUT_PACKET_SIZE];
USB_DMA_NONINIT_DATA_ALIGN(USB_DATA_ALIGN_SIZE) static uint8_t bulk_send_buffer[FS_BULK_DEVICE_IN_PACKET_SIZE];
static usb_device_composite_struct_t *s_UsbDeviceComposite;

static volatile uint32_t usb_bulk_send_ok;

/* The device BULK class callback */
usb_status_t USB_DeviceBulkCustomCallback(class_handle_t handle, uint32_t event, void *param)
{
    usb_status_t error = kStatus_USB_Error;

    switch (event)
    {
        case kUSB_DeviceBulkEventSendResponse:
            {
                usb_bulk_send_ok = 1 ;
            }
            break;
        case kUSB_DeviceBulkEventRecvResponse:
            {
                usb_device_endpoint_callback_message_struct_t *msg = (usb_device_endpoint_callback_message_struct_t *)param;
                if(msg->length <= FS_BULK_DEVICE_OUT_PACKET_SIZE)
                {
                    USB_DeviceBulkReceiveData(msg->buffer,msg->length);
                }
            }
            break;
        case kUSB_DeviceBulkEventGetReport:
        case kUSB_DeviceBulkEventSetReport:
            break;
        case kUSB_DeviceBulkEventRequestReportBuffer:
            {
                (void)USB_DeviceBulkRecv(handle, USB_BULK_DEVICE_OUT_ENDPOINT, bulk_rec_buffer,sizeof(bulk_rec_buffer));
                error = kStatus_USB_Success;
            }
            break;
        case kUSB_DeviceBulkEventGetIdle:
        case kUSB_DeviceBulkEventGetProtocol:
        case kUSB_DeviceBulkEventSetIdle:
        case kUSB_DeviceBulkEventSetProtocol:
            break;
        default:
            break;
    }

    return error;
}



/* The device callback */
usb_status_t USB_DeviceBulkCustomSetConfigure(class_handle_t handle, uint8_t configure)
{
    return kStatus_USB_Success;
}

/* Set interface */
usb_status_t USB_DeviceBulkCustomSetInterface(class_handle_t handle, uint8_t interface, uint8_t alternateSetting)
{
    return kStatus_USB_Success;
}
/* Initialize the BULK */
usb_status_t USB_DeviceBulkCustomInit(usb_device_composite_struct_t *deviceComposite)
{
    s_UsbDeviceComposite       = deviceComposite;
    usb_bulk_send_ok = 0 ;
    return kStatus_USB_Success;
}

usb_status_t USB_DeviceBulkStartRecv(void)
{
    usb_status_t error = kStatus_USB_Error;
    error = USB_DeviceBulkRecv(s_UsbDeviceComposite->bulkCustom.bulkHandle , USB_BULK_DEVICE_OUT_ENDPOINT, bulk_rec_buffer,sizeof(bulk_rec_buffer));
    return error;
}

usb_status_t USB_DeviceBulkStartSend(uint8_t *buffer,uint32_t length)
{
    usb_status_t status = kStatus_USB_Success;
    uint32_t ok;

    while(length)
    {
        usb_bulk_send_ok = 0 ;
        status = USB_DeviceBulkSend(s_UsbDeviceComposite->bulkCustom.bulkHandle,USB_BULK_DEVICE_IN_ENDPOINT,(uint8_t *)buffer,FS_BULK_DEVICE_IN_PACKET_SIZE);
        if(status != kStatus_USB_Success)
        {
            return kStatus_USB_TransferFailed;
        }
        uint32_t tick = xTaskGetTickCount() + pdMS_TO_TICKS(500);
        while(usb_bulk_send_ok == 0)
        {
            if(xTaskGetTickCount() >= tick)
            {
                return kStatus_USB_TransferFailed;
            }
        }
        buffer += FS_BULK_DEVICE_IN_PACKET_SIZE;
        length -= (length >= FS_BULK_DEVICE_IN_PACKET_SIZE) ? FS_BULK_DEVICE_IN_PACKET_SIZE : length;
    }
    return status;
}

__WEAK void USB_DeviceBulkReceiveData(uint8_t *buffer,uint32_t length)
{
    USB_DeviceBulkStartRecv();
}


#endif
